<template>
  <view class="dl-tree" hover-class="none" hover-stop-propagation="false">
    <view v-if="showSearch" class="search-wrap" hover-class="none" hover-stop-propagation="false">
      <u-search placeholder="搜索" v-model.trim="keyword" bgColor="#ffffff" shape="shape" :showAction="false" height="88rpx"></u-search>
    </view>
    <view v-if="root && root.childNodes.length" class="tree-node-wrap">
      <tree-node v-for="(node, index) in root.childNodes" :key="index" :node="node" />
    </view>
    <u-empty v-else :icon="noDataIcon" width="360rpx" text="暂无搜索结果" margin-top="200rpx"> </u-empty>
    <u-loading-page :loading="rootLoading"></u-loading-page>
  </view>
</template>

<script>
import treeNode from './tree-node.vue'
import noData from '@/static/images/no-data.png'

let nodeIdSeed = 0
export default {
  name: 'DlTree',
  components: {
    treeNode
  },
  props: {
    defaultCheckedNodes: {
      type: Array,
      default: () => []
    },
    setTreeData: {
      type: Function,
      require: true
    },
    hasChildrenKey: {
      type: String,
      default: ''
    },
    showSearch: {
      type: Boolean,
      default: true
    },
    showCheckbox: {
      type: Boolean,
      default: true
    },
    onlyCheckLeaf: {
      type: Boolean,
      default: true
    },
    onlyCheckParent: {
      type: Boolean,
      default: false
    },
    noDataIcon: {
      type: String,
      default: noData
    },
    showLeafIcon: {
      type: Boolean,
      default: false
    },
    isRadio: {
      type: Boolean,
      default: false
    },
    expand: {
      type: Boolean,
      default: false
    },
    filterNodeMethod: Function,
    leafTypeVal: {
      type: String,
      default: ''
    },
    checkedOnClickNode: {
      type: Boolean,
      default: true
    },
    treeNodeAllLeaf: {
      type: Boolean,
      default: false
    },
    isSingleCheck: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      keyword: null,
      rootLoading: false,
      searchLoading: false,
      root: null,
      checkedNodes: []
    }
  },
  watch: {
    defaultCheckedNodes: function (newVal) {
      if (newVal && newVal?.length) {
        if (this.isRadio) {
          setTimeout(() => {
            this.setRadioChecked(this.root.childNodes, newVal[0].id)
            this.$emit('checkRadio', { checkedNodes: this.checkedNodes })
          }, 500)
        } else {
          this.checkedNodes = newVal.map(i => ({ data: i }))
          this.$emit('check', { checkedNodes: this.checkedNodes })
        }
      }
      // if (newVal && newVal?.length) {
      //   this.checkedNodes = newVal.map(i => ({ data: i }))
      // }
    }
  },
  created() {
    this.isTree = true
    if (this.setTreeData) {
      this.generateRootNode()
    }
    if (this.showSearch) {
      this.$watch('keyword', function (newVal) {
        this.filter(newVal)
      })
    }
  },
  methods: {
    generateRootNode() {
      this.rootLoading = true
      const getNodeByData = (nodeData, level = 0, parentNode) => {
        const isRoot = level === 0
        const node = {
          data: isRoot ? { children: nodeData } : nodeData,
          id: nodeIdSeed++,
          level,
          isLeaf: !isRoot && this.checkNodeIsLeaf(nodeData),
          expanded: isRoot,
          checked: !isRoot && this.defaultCheckedNodes.map(i => i.id).indexOf(nodeData.id) > -1 ? [nodeData.id] : [],
          visible: true,
          childNodes: [],
          siblingIsNonLeaf: false,
          isRadio: false
        }
        if (isRoot) {
          level++
          node.childNodes = nodeData.map(item => getNodeByData(item, level, node))
        } else {
          if (nodeData.children && nodeData.children?.length) {
            level++
            node.childNodes = nodeData.children.map(item => getNodeByData(item, level, node))
          }
          node.siblingIsNonLeaf = node.isLeaf && parentNode.data.children.some(i => !this.checkNodeIsLeaf(i))
        }
        return node
      }
      const callback = sData => {
        this.root = getNodeByData(sData)
        this.rootLoading = false
      }
      this.setTreeData(callback)
    },
    checkNodeIsLeaf(data) {
      if (this.isRadio) return false
      const dataIsLeaf = !!data.isLeaf
      const isLeafType = this.leafTypeVal && data.type === this.leafTypeVal
      const hasNoChildren = this.hasChildrenKey && !data[this.hasChildrenKey]
      if (this.treeNodeAllLeaf) {
        return hasNoChildren
      }
      if (this.isRadio) return false
      return dataIsLeaf || isLeafType || hasNoChildren
    },
    filter(value) {
      const traverse = function (node) {
        const childNodes = node.childNodes
        childNodes.forEach(child => {
          child.visible = child.data.name.indexOf(value) !== -1
          traverse(child)
        })
        if (!node.visible && node.expanded && childNodes.length) {
          node.visible = childNodes.some(child => child.visible)
        }
      }
      traverse(this.root)
    },
    setRadioChecked(childNodes, id) {
      for (let i = 0; i < childNodes.length; i++) {
        if (childNodes[i].data.id === id) {
          childNodes[i].isRadio = true
          this.checkedNodes = { data: { id: childNodes[i].data.id, name: childNodes[i].data.name } }
        }
        this.setRadioChecked(childNodes[i].childNodes, id)
      }
    }
  }
}
</script>

<style lang="scss"></style>
